package com.info.protocol.netty.core.codec;

import com.info.protocol.constants.CommonConstant;
import com.info.protocol.enums.MessageTypeEnum;
import com.info.protocol.netty.core.Header;
import com.info.protocol.netty.core.Protocol;
import com.info.protocol.netty.core.Request;
import com.info.protocol.netty.core.Response;
import com.info.protocol.serial.Serializer;
import com.info.protocol.serial.SerializerManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class CustomDecoder extends ByteToMessageDecoder {

        /*
        +--------------------------------------------------------------------------------------------+
        |魔数 16bit|协议版本 8bit|序列化方式 8bit|消息长度 32bit |消息类型（请求还是响应）2bit|messageId 64bit |
        +--------------------------------------------------------------------------------------------+
        */

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        log.info("------------------ begin decode ------------------");
        if (in.readableBytes() < CommonConstant.HEADER_LENGTH) {
            // 消息长度不够，暂不解析
            return;
        }
        //标记一个读取数据的索引，必要的时候用来重置。
        in.markReaderIndex();

        final short magic = in.readShort();
        if (magic != CommonConstant.MAGIC) {
            throw new IllegalArgumentException("illegal request parameter 'magic' " + magic);
        }
        final byte protocolVersionCode = in.readByte();
        final byte serializerTypeCode = in.readByte();
        final int messageLength = in.readInt();
        final byte messageTypeCode = in.readByte();
        final long messageId = in.readLong();
        // 如果可读字节数小于消息长度，说明消息还不完整。
        if (in.readableBytes() < messageLength) {
            // 消息不够 重置读标识
            in.resetReaderIndex();
            return;
        }
        byte[] content = new byte[messageLength];
        in.readBytes(content);

        Header header = new Header();
        header.setMagic(magic)
                .setMessageId(messageId)
                .setMessageLength(messageLength)
                .setMessageType(messageTypeCode)
                .setProtocolVersion(protocolVersionCode)
                .setSerializeType(serializerTypeCode);

        // 获取反序列器
        final Serializer serializer = SerializerManager.getSerializerByCode(serializerTypeCode);
        MessageTypeEnum messageType = MessageTypeEnum.getMessageTypeEnumByCode(messageTypeCode);

        switch (messageType) {
            case REQUEST:
                final Request request = serializer.deserialize(content, Request.class);
                Protocol<Request> requestProtocol = new Protocol<>();
                requestProtocol.setHeader(header);
                requestProtocol.setContent(request);
                out.add(requestProtocol);
                break;
            case RESPONSE:
                final Response response = serializer.deserialize(content, Response.class);
                Protocol<Response> responseProtocol = new Protocol<>();
                responseProtocol.setHeader(header);
                responseProtocol.setContent(response);
                out.add(responseProtocol);
                break;
            case HEART_BEAT:
            default:
        }

    }
}
